#include "views.h"
#include "ttorrent.h"
#include "nls.h"

#include <glib.h>
#include <string.h>


GtkListStore * create_files_store(){
  return gtk_list_store_new(
      NUM_F_COLS,
      G_TYPE_INT, // order
      G_TYPE_INT,// priority
      G_TYPE_INT,// prev_priority
      G_TYPE_UINT64,// size
      G_TYPE_STRING, // path
      G_TYPE_FLOAT, // progress
      G_TYPE_POINTER // edited
    );
}

void selection_changed(GtkTreeSelection * sel, gpointer data)
{
    GtkTreeModel * model;
    GtkTreeIter    iter;
    GtkWidget * child;

    gboolean valid = FALSE;
    TTorrent * ttorrent = (TTorrent *) data;
    gpointer th = NULL;
    gpointer ti = NULL;
    gpointer table = NULL;
    gpointer files = NULL;

    valid = gtk_tree_selection_get_selected(sel, &model, &iter);

    if (valid)
      gtk_tree_model_get (model, &iter,
        COL_T_HANDLE, &th,
        COL_T_FILES, &files,
        COL_T_TABLE, &table,
        -1
      );

    if ((ttorrent->handle != th) || (th == NULL))
    {
        ttorrent->handle = th;

        model = gtk_tree_view_get_model(GTK_TREE_VIEW(ttorrent->peers_view));
        model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(model));
        gtk_list_store_clear(GTK_LIST_STORE(model));

        model = gtk_tree_view_get_model(GTK_TREE_VIEW(ttorrent->blocks_view));
        model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(model));
        gtk_list_store_clear(GTK_LIST_STORE(model));

        if(table == NULL)
          table = (gpointer) create_info_view();

        child = gtk_bin_get_child(GTK_BIN(ttorrent->info_view));
        gtk_container_remove(GTK_CONTAINER(ttorrent->info_view), child);
        gtk_container_add(GTK_CONTAINER(ttorrent->info_view), GTK_WIDGET(table));
        gtk_widget_show_all(ttorrent->info_view);

        if(files == NULL)
        {
          GtkListStore * store = GTK_LIST_STORE(create_files_store());

          files = (gpointer) gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(store));
          g_object_unref(store);

        }

        gtk_tree_view_set_model(GTK_TREE_VIEW(ttorrent->files_view), GTK_TREE_MODEL(files));
    }
};


void
priority_edit_done_cb(
  GtkCellRendererText *renderer,
  gchar *path,
  gchar *new_text,
  gpointer data
)
{
  GtkTreeIter iter;
  GtkTreeIter sort_iter;
  GtkTreeModel * sort_model = gtk_tree_view_get_model(GTK_TREE_VIEW(data));
  GtkTreeModel * model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(sort_model));
  gboolean valid = gtk_tree_model_get_iter_from_string(sort_model,&sort_iter, path);

  gint newval = (gint) g_ascii_strtod(new_text, NULL);
  gint oldval;
  gint setval;
  gint * edited;

  gtk_tree_model_get( sort_model, &sort_iter,
    COL_F_PRIORITY, &setval,
    COL_F_NEW_PRI, &oldval,
    COL_F_EDITED, &edited,
    -1
  );

  *edited = 0;
  if(oldval == newval) return;

  gtk_tree_model_sort_convert_iter_to_child_iter(GTK_TREE_MODEL_SORT(sort_model), &iter, &sort_iter);
  gtk_list_store_set(GTK_LIST_STORE(model), &iter,
    COL_F_NEW_PRI, newval,
  -1);
}

void priority_edit_start_cb(
  GtkCellRenderer *renderer,
  GtkCellEditable *editable,
  gchar *path,
  gpointer data
)
{
  GtkTreeIter iter;
  GtkTreeModel * model = gtk_tree_view_get_model(GTK_TREE_VIEW(data));
  gboolean valid = gtk_tree_model_get_iter_from_string(model,&iter, path);

  gint * edited;

  if(!valid) return;
  gtk_tree_model_get( model, &iter,
    COL_F_EDITED, &edited,
    -1
  );
  *edited = 1;
}

void
float_data_func
(
  GtkTreeViewColumn * col,
  GtkCellRenderer * cell,
  GtkTreeModel * model,
  GtkTreeIter * iter,
  gpointer data
)
{
  gfloat value;
  gchar* buf;
  gint   col_id;

  col_id = gtk_tree_view_column_get_sort_column_id(col);

  gtk_tree_model_get(model, iter, col_id, &value, -1);

  if(value>=0.0)
  {
    buf = g_strdup_printf("%.1f", value);
    g_object_set(cell, "text", buf, NULL);
    g_free(buf);
    return;
  }
  g_object_set(cell, "text", "", NULL);
}

void
size_data_func
(
  GtkTreeViewColumn * col,
  GtkCellRenderer * cell,
  GtkTreeModel * model,
  GtkTreeIter * iter,
  gpointer data
)
{
  guint64 x;
  gchar* buf;
  gint  col_id;

  col_id = gtk_tree_view_column_get_sort_column_id(col);
  if(col_id<=0) return;


  gtk_tree_model_get(model, iter, col_id, &x, -1);

  if(x<1024)
    buf = g_strdup_printf("%llu B", x);
  else if(x<1024*1024)
    buf = g_strdup_printf("%.1f KB", (gfloat) x/1024);
  else if(x<1024*1024*1024)
    buf = g_strdup_printf("%.1f MB", (gfloat) x/(1024*1024));
  else
    buf = g_strdup_printf("%.1f GB", (gfloat) x/(1024*1024*1024));

  g_object_set(cell, "text", buf, NULL);
  g_free(buf);
}

void
state_data_func
(
  GtkTreeViewColumn * col,
  GtkCellRenderer * cell,
  GtkTreeModel * model,
  GtkTreeIter * iter,
  gpointer data
)
{
  guint state;
  gtk_tree_model_get(model, iter,
      COL_T_STATE, &state,
      -1);

  g_object_set(cell, "stock-size", GTK_ICON_SIZE_MENU, NULL);

  switch(state)
  {
    case S_ACTIVE: g_object_set(cell, "stock-id", GTK_STOCK_MEDIA_PLAY, NULL);
    break;
    case S_PAUSED: g_object_set(cell, "stock-id", GTK_STOCK_MEDIA_PAUSE, NULL);
    break;
    case S_DONE: g_object_set(cell, "stock-id", GTK_STOCK_YES, NULL);
    break;
    default:
      g_object_set(cell, "stock-id", GTK_STOCK_DIALOG_ERROR, NULL);
  }
}

void
client_data_func
(
  GtkTreeViewColumn * col,
  GtkCellRenderer * cell,
  GtkTreeModel * model,
  GtkTreeIter * iter,
  gpointer data
)
{
  gchar* buf;

  gtk_tree_model_get(model, iter, COL_P_CLIENT, &buf, -1);

  if(g_utf8_validate(buf, -1, NULL))
  {
    g_object_set(cell, "text", buf, NULL);
    g_free(buf);
  }
  else
  {
    gchar* nbuf;
    gint br;
    gint bw;
    GIConv conv;
    GError * error;
    error = NULL;
    conv = g_iconv_open("utf8", "iso8859-1");
    nbuf = g_convert_with_iconv(buf, -1, conv, &br, &bw, &error);
    g_iconv_close(conv);

    if(error)
    {
      g_free(error);
      g_object_set(cell, "text", "???", NULL);
    }
    else g_object_set(cell, "text", nbuf, NULL);

    g_free(buf);
    g_free(nbuf);
  }
}

void flags_data_func
(
  GtkTreeViewColumn * col,
  GtkCellRenderer * cell,
  GtkTreeModel * model,
  GtkTreeIter * iter,
  gpointer data
)
{
  guint flags;
  gchar buf[8];

  gtk_tree_model_get(model, iter, COL_P_FLAGS, &flags, -1);

  buf[0]= ( flags & 0x1 ? 'i' : '_');
  buf[1]= ( flags & 0x2 ? 'c' : '_');
  buf[2]= ( flags & 0x4 ? 'I' : '_');
  buf[3]= ( flags & 0x8 ? 'C' : '_');
  buf[4]= ( flags & 0x10 ? 'e' : '_');
  buf[5]= ( flags & 0x20 ? '-' : '+');
  buf[6] = 0;

  g_object_set(cell, "text", buf, NULL);
}

void
peers_data_func
(
  GtkTreeViewColumn * col,
  GtkCellRenderer * cell,
  GtkTreeModel * model,
  GtkTreeIter * iter,
  gpointer data
)
{
  gint col_id;
  gint peers;
  gint peers_swarm;
  gchar* buf;

  col_id = gtk_tree_view_column_get_sort_column_id(col);
  if(col_id<=0) return;

  gtk_tree_model_get(model, iter,
      col_id, &peers,
      col_id+1, &peers_swarm,
      -1);

  if(peers<0)
    buf = g_strdup_printf("");
  else if(peers_swarm<0)
    buf = g_strdup_printf("%d", peers);
  else
    buf = g_strdup_printf("%d (%d)", peers, peers_swarm);

  g_object_set(cell, "text", buf, NULL);
  g_free(buf);
}


//**********************************************************************
//* create views
//**********************************************************************

GtkTreeView*
create_peers_view(){
    GtkListStore * store;
    GtkTreeModel * model;
    GtkWidget * widget;
    GtkTreeView * view;
    GtkCellRenderer *cell;
    GtkTreeViewColumn *col;
    GtkTreeSelection *sel;
    GtkLabel * label;

    store = gtk_list_store_new(
      NUM_P_COLS,
      G_TYPE_STRING, //ip
      G_TYPE_FLOAT,  //download
      G_TYPE_FLOAT,  // upload
      G_TYPE_STRING, // client
      G_TYPE_UINT  // flags
    );

    model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(store));
    g_object_unref(store);

    widget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
    g_object_unref(model);

    view = GTK_TREE_VIEW(widget);

    cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_P_IP);
    gtk_tree_view_column_set_title (col, _("IP"));
    gtk_tree_view_append_column (view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_P_IP);

    cell = gtk_cell_renderer_text_new ();
    g_object_set(cell, "xalign", 1.0, NULL);
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    //gtk_tree_view_column_add_attribute (col, cell, "text", COL_P_DOWN);
    //gtk_tree_view_column_add_attribute (col, cell, "xalign", COL_P_ALIGN);
    gtk_tree_view_column_set_title (col, _("Download"));
    gtk_tree_view_append_column (view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_P_DOWN);
    gtk_tree_view_column_set_cell_data_func(col, cell, float_data_func, NULL, NULL);

    //cell = gtk_cell_renderer_text_new ();
    //g_object_set(cell, "xalign", 1.0, NULL);
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    //gtk_tree_view_column_add_attribute (col, cell, "text", COL_P_UP);
    //gtk_tree_view_column_add_attribute (col, cell, "xalign", COL_P_ALIGN);
    gtk_tree_view_column_set_title (col, _("Upload"));
    gtk_tree_view_append_column (view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_P_UP);
    gtk_tree_view_column_set_cell_data_func(col, cell, float_data_func, NULL, NULL);

    cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    //gtk_tree_view_column_add_attribute (col, cell, "text", COL_P_CLIENT);
    gtk_tree_view_column_set_title (col, _("Client"));
    gtk_tree_view_append_column (view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_P_CLIENT);
    gtk_tree_view_column_set_cell_data_func(col, cell, client_data_func, NULL, NULL);

    cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_P_FLAGS);
    gtk_tree_view_column_set_title (col, _("Flags"));
    gtk_tree_view_append_column (view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_P_FLAGS);
    gtk_tree_view_column_set_cell_data_func(col, cell, flags_data_func, NULL, NULL);
    g_object_set(G_OBJECT(cell), "family", "Monospace");
    g_object_set(G_OBJECT(cell), "family-set", TRUE);

    sel = gtk_tree_view_get_selection(view);
    gtk_tree_selection_set_mode (sel, GTK_SELECTION_NONE );

    return view;
};

GtkTreeView*
create_blocks_view(){
    GtkListStore * store;
    GtkTreeModel * model;
    GtkTreeView * view;
    GtkWidget * widget;
    GtkCellRenderer *cell;
    GtkTreeViewColumn *col;

    store = gtk_list_store_new(
      NUM_B_COLS,
      G_TYPE_INT, //index
      G_TYPE_INT, //have pieces
      G_TYPE_INT, //all pieces
      G_TYPE_FLOAT //progress
    );
    model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(store));
    g_object_unref(store);
    widget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
    g_object_unref(model);

    view = GTK_TREE_VIEW(widget);

    cell = gtk_cell_renderer_text_new ();
    g_object_set(cell, "xalign", 1.0, NULL);
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_B_INDEX);
    //gtk_tree_view_column_add_attribute (col, cell, "xalign", COL_B_ALIGN);
    gtk_tree_view_column_set_title (col, _("#"));
    gtk_tree_view_column_set_sort_column_id(col, COL_B_INDEX);
    gtk_tree_view_append_column (view, col);

    cell = gtk_cell_renderer_text_new ();
    g_object_set(cell, "xalign", 1.0, NULL);
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_B_HAVE);
    gtk_tree_view_column_set_title (col, _("Downloaded blocks"));
    gtk_tree_view_column_set_sort_column_id(col, COL_B_HAVE);
    gtk_tree_view_append_column (view, col);

    cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_B_MAX);
    gtk_tree_view_column_set_title (col, _("All blocks"));
    gtk_tree_view_column_set_sort_column_id(col, COL_B_MAX);
    gtk_tree_view_append_column (view, col);

    cell = gtk_cell_renderer_progress_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    gtk_tree_view_column_add_attribute (col, cell, "value", COL_B_PROGRESS);
    gtk_tree_view_column_set_title (col, _("Progress"));
    gtk_tree_view_column_set_sort_column_id(col, COL_B_PROGRESS);
    gtk_tree_view_append_column (view, col);

    return view;
};

GtkTreeView*
create_files_view()
{
    GtkListStore * store;
    GtkTreeModel * model;
    GtkTreeView * view;
    GtkWidget * widget;
    GtkCellRenderer *cell;
    GtkTreeViewColumn *col;
    GtkTreeSelection * sel;

    store = create_files_store();

    model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(store));
    g_object_unref(store);

    widget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
    g_object_unref(model);

    view = GTK_TREE_VIEW(widget);

    cell = gtk_cell_renderer_text_new ();
    g_object_set(cell, "xalign", 1.0, NULL);
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_F_ORDER);
    //gtk_tree_view_column_add_attribute (col, cell, "xalign", COL_F_ALIGN);
    gtk_tree_view_column_set_title (col, _("#"));
    gtk_tree_view_column_set_sort_column_id(col, COL_F_ORDER);
    gtk_tree_view_append_column (view, col);


    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_F_PRIORITY);
    gtk_tree_view_column_set_title (col, _("Priority"));
    gtk_tree_view_column_set_sort_column_id(col, COL_F_PRIORITY);
    gtk_tree_view_append_column (view, col);

    cell = gtk_cell_renderer_spin_new();
    g_object_set(cell, "editable", TRUE, NULL);
    g_signal_connect(cell, "editing-started", (GCallback) priority_edit_start_cb, (gpointer) view);
    g_signal_connect(cell, "edited", (GCallback) priority_edit_done_cb, (gpointer) view);
    g_object_set(cell, "adjustment", gtk_adjustment_new(1.0, 0.0, 7.0, 1.0, 1.0, 1.0), NULL);
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_F_NEW_PRI);
    gtk_tree_view_column_set_title (col, _("New Priority"));
    gtk_tree_view_column_set_sort_column_id(col, COL_F_NEW_PRI);
    gtk_tree_view_append_column (view, col);

    cell = gtk_cell_renderer_text_new ();
    g_object_set(cell, "xalign", 1.0, NULL);
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    gtk_tree_view_column_set_title (col, _("Size"));
    gtk_tree_view_column_set_sort_column_id(col, COL_F_SIZE);
    gtk_tree_view_append_column (view, col);
    gtk_tree_view_column_set_cell_data_func(col, cell, size_data_func, NULL, NULL);

    cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_F_PATH);
    gtk_tree_view_column_set_title (col, _("Path"));
    gtk_tree_view_column_set_sort_column_id(col, COL_F_PATH);
    gtk_tree_view_append_column (view, col);

    cell = gtk_cell_renderer_progress_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    gtk_tree_view_column_add_attribute (col, cell, "value", COL_F_PROGRESS);
    gtk_tree_view_column_set_title (col, _("Progress"));
    gtk_tree_view_column_set_sort_column_id(col, COL_F_PROGRESS);
    gtk_tree_view_append_column (view, col);

    sel = gtk_tree_view_get_selection (view);
    gtk_tree_selection_set_mode (sel, GTK_SELECTION_BROWSE );

    return view;
}



GtkWidget *
create_torrents_view (TTorrent * ttorrent)
{
    GtkCellRenderer *cell;
    GtkTreeViewColumn *col;
    GtkTreeModel *model;
    GtkListStore *store;
    GtkTreeSelection * sel;
    GtkWidget * widget;

    store = gtk_list_store_new (NUM_T_COLS,
      G_TYPE_POINTER, //torrent_handle
      G_TYPE_POINTER, //info_model
      G_TYPE_POINTER, //files_model
      G_TYPE_POINTER, //priorities
      G_TYPE_INT, //num_files
      G_TYPE_INT, //order
      G_TYPE_STRING, //name
      G_TYPE_STRING, //SHA
      G_TYPE_INT64, //size
      G_TYPE_UINT, //state
      G_TYPE_INT, G_TYPE_INT, //seeds/peers
      G_TYPE_INT, G_TYPE_INT, //peers
      G_TYPE_FLOAT, G_TYPE_FLOAT, //download/upload
      G_TYPE_UINT64, G_TYPE_UINT64, //downloaded/uploaded (previous session)
      G_TYPE_UINT64, G_TYPE_UINT64, //downloaded/uploaded (session)
      G_TYPE_FLOAT, // ratio
      G_TYPE_FLOAT //progress
    );

    model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(store));
    g_object_unref(store);

    widget = gtk_tree_view_new_with_model (model);
    g_object_unref(model);

    ttorrent->torrents_view = GTK_TREE_VIEW(widget);

    cell = gtk_cell_renderer_text_new ();
    g_object_set(cell, "xalign", 1.0, NULL);
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_T_NUMBER);
    gtk_tree_view_column_set_title (col, _("#"));
    gtk_tree_view_append_column (ttorrent->torrents_view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_T_NUMBER);

    cell = gtk_cell_renderer_pixbuf_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    //gtk_tree_view_column_add_attribute (col, cell, "stock_id", COL_T_STATE);
    gtk_tree_view_column_set_title (col, _("State"));
    gtk_tree_view_append_column (ttorrent->torrents_view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_T_STATE);
    gtk_tree_view_column_set_cell_data_func(col, cell, state_data_func, NULL, NULL);


    cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    gtk_tree_view_column_add_attribute (col, cell, "text", COL_T_NAME);
    gtk_tree_view_column_set_title (col, _("Name"));
    gtk_tree_view_append_column (ttorrent->torrents_view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_T_NAME);

    cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    //gtk_tree_view_column_add_attribute (col, cell, "text", COL_T_SIZE);
    gtk_tree_view_column_set_title (col, _("Size"));
    gtk_tree_view_append_column (ttorrent->torrents_view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_T_SIZE);
    gtk_tree_view_column_set_cell_data_func(col, cell, size_data_func, NULL, NULL);

    //cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    //gtk_tree_view_column_add_attribute (col, cell, "text", COL_T_SEEDS);
    gtk_tree_view_column_set_title (col, _("Seeds"));
    gtk_tree_view_append_column (ttorrent->torrents_view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_T_SEEDS);
    gtk_tree_view_column_set_cell_data_func(col, cell, peers_data_func, NULL, NULL);

    //cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    //gtk_tree_view_column_add_attribute (col, cell, "text", COL_T_PEERS);
    gtk_tree_view_column_set_title (col, _("Peers"));
    gtk_tree_view_append_column (ttorrent->torrents_view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_T_PEERS);
    gtk_tree_view_column_set_cell_data_func(col, cell, peers_data_func, NULL, NULL);

    cell = gtk_cell_renderer_text_new ();
    g_object_set(cell, "xalign", 1.0, NULL);
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    //gtk_tree_view_column_add_attribute (col, cell, "text", COL_T_DOWN_SPEED);
    //gtk_tree_view_column_add_attribute (col, cell, "xalign", COL_T_ALIGN);
    gtk_tree_view_column_set_title (col, _("Download"));
    gtk_tree_view_append_column (ttorrent->torrents_view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_T_DOWN_SPEED);
    gtk_tree_view_column_set_cell_data_func(col, cell, float_data_func, NULL, NULL);

    //cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    //gtk_tree_view_column_add_attribute (col, cell, "text", COL_T_UP_SPEED);
    //gtk_tree_view_column_add_attribute (col, cell, "xalign", COL_T_ALIGN);
    gtk_tree_view_column_set_title (col, _("Upload"));
    gtk_tree_view_append_column (ttorrent->torrents_view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_T_UP_SPEED);
    gtk_tree_view_column_set_cell_data_func(col, cell, float_data_func, NULL, NULL);

    cell = gtk_cell_renderer_progress_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, TRUE);
    gtk_tree_view_column_add_attribute (col, cell, "value", COL_T_PROGRESS);
    gtk_tree_view_column_set_title (col, _("Progress"));
    gtk_tree_view_append_column (ttorrent->torrents_view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_T_PROGRESS);

    cell = gtk_cell_renderer_text_new ();
    col = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_resizable (col, TRUE);
    gtk_tree_view_column_pack_start (col, cell, FALSE);
    gtk_tree_view_column_set_title (col, _("Ratio"));
    gtk_tree_view_append_column (ttorrent->torrents_view, col);
    gtk_tree_view_column_set_sort_column_id(col, COL_T_RATIO);
    gtk_tree_view_column_set_cell_data_func(col, cell, float_data_func, NULL, NULL);

    sel = gtk_tree_view_get_selection (ttorrent->torrents_view);
    gtk_tree_selection_set_mode (sel, GTK_SELECTION_BROWSE );
    g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK (selection_changed), (gpointer) ttorrent);

    widget = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET(ttorrent->torrents_view));

    return widget;
};

GtkWidget *
create_statusbar(TTorrent * tt)
{
  GtkBox * hbox;
  GtkBox * bar;
  GtkWidget * widget;

  bar = GTK_BOX(gtk_hbox_new(FALSE, 0));

  hbox = GTK_BOX(gtk_hbox_new(FALSE, 0));
  gtk_box_pack_start(hbox, gtk_image_new_from_stock(GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU), FALSE, FALSE, 0);
  gtk_box_pack_start(hbox, gtk_label_new(""), FALSE, FALSE, 0);
  gtk_box_pack_start(hbox, gtk_label_new(""), TRUE, TRUE, 10);
  gtk_box_pack_start(hbox, gtk_image_new_from_stock(GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU), FALSE, FALSE, 0);
  gtk_box_pack_start(hbox, gtk_label_new(""), FALSE, FALSE, 0);

  gtk_box_pack_start(hbox, gtk_label_new(""), TRUE, TRUE, 10);
  gtk_box_pack_start(hbox, gtk_image_new_from_stock(GTK_STOCK_CONNECT, GTK_ICON_SIZE_MENU), FALSE, FALSE, 0);
  gtk_box_pack_start(hbox, gtk_label_new(""), FALSE, FALSE, 0);
  gtk_box_pack_start(hbox, gtk_label_new(""), TRUE, TRUE, 10);
  gtk_box_pack_start(hbox, gtk_image_new_from_stock(GTK_STOCK_NETWORK, GTK_ICON_SIZE_MENU), FALSE, FALSE, 0);
  gtk_box_pack_start(hbox, gtk_label_new(""), FALSE, FALSE, 0);
  gtk_box_pack_start(hbox, gtk_label_new(""), TRUE, TRUE, 10);
  gtk_box_pack_start(hbox, gtk_image_new_from_stock(GTK_STOCK_NO, GTK_ICON_SIZE_MENU), FALSE, FALSE, 0);
  widget = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(widget), GTK_WIDGET(hbox));
  gtk_box_pack_start(bar, widget, TRUE, TRUE, 0);

  gtk_box_pack_start(bar, gtk_statusbar_new(), TRUE, TRUE, 0);

  tt->statusbar = GTK_WIDGET(hbox);
  return GTK_WIDGET(bar);
}

void
update_statusbar(GtkWidget * widget, TStatus * ts)
{
  gint x = 0;
  GList * list = gtk_container_get_children(GTK_CONTAINER(widget));
  gchar* buf;

  while(list != NULL)
  {
    switch(x){
      case  1:
        buf = g_strdup_printf("%.1f", ts->down_speed);
        gtk_label_set_label(GTK_LABEL(list->data), buf);
        g_free(buf);
        ++x; list = list->next;
      break;
      case  4:
        buf = g_strdup_printf("%.1f", ts->up_speed);
        gtk_label_set_label(GTK_LABEL(list->data), buf);
        g_free(buf);
        ++x; list = list->next;
      break;
      case  7:
        buf = g_strdup_printf("%d", ts->num_peers);
        gtk_label_set_label(GTK_LABEL(list->data), buf);
        g_free(buf);
        ++x; list = list->next;
      break;
      case 10:
        buf = g_strdup_printf("%d", ts->dht_nodes);
        gtk_label_set_label(GTK_LABEL(list->data), buf);
        g_free(buf);
        ++x; list = list->next;
      break;
      case 12:
        gtk_image_set_from_stock(GTK_IMAGE(list->data), (ts->has_incoming ? GTK_STOCK_YES : GTK_STOCK_NO), GTK_ICON_SIZE_MENU);
      default:
        ++x; list = list->next;
    }
  }
}

void query_torrents(GtkTreeView * view, GKeyFile * kf)
{
  gboolean valid;
  GtkTreeIter iter;
  GtkTreeModel * model = gtk_tree_view_get_model(view);
  model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(model));
  valid = gtk_tree_model_get_iter_first(model, &iter);

  gchar * sha;
  guint64 u_prev, u_sess;
  guint64 d_prev, d_sess;

  while(valid)
  {
    gtk_tree_model_get(model, &iter,
      COL_T_SHA, &sha,
      COL_T_DOWN_PREV, &d_prev, COL_T_DOWN_SESS, &d_sess,
      COL_T_UP_PREV, &u_prev, COL_T_UP_SESS, &u_sess,
      -1
    );
    d_sess += d_prev;
    u_sess += u_prev;
    g_key_file_set_integer(kf, sha, "downloaded_h", (gint) d_sess / (1024*1024*1024));
    g_key_file_set_integer(kf, sha, "downloaded_l", (gint) d_sess % (1024*1024*1024));
    g_key_file_set_integer(kf, sha, "uploaded_h", (gint) u_sess / (1024*1024*1024));
    g_key_file_set_integer(kf, sha, "uploaded_l", (gint) u_sess % (1024*1024*1024));

    //g_free(sha);
    valid = gtk_tree_model_iter_next(model, &iter);
  }
}

void
int_value_changed(
  GtkSpinButton * button,
  gpointer data
)
{
  gint* value = data;
  *value = gtk_spin_button_get_value_as_int(button);
}

void
float_value_changed(
  GtkSpinButton * button,
  gpointer data
)
{
  gint* value = data;
  *value = gtk_spin_button_get_value_as_float(button);
}

void
enum_value_changed(
  GtkComboBox *widget,
  gpointer     data
)
{
  gint * value = (gint *) data;
  gint active = gtk_combo_box_get_active(widget);
  if (active < 0) return;
  *value = active;
}

GtkWidget * create_options_view(TSettings * ts)
{
    GtkTable * table = GTK_TABLE(gtk_table_new(8, 10, FALSE));
    GtkWidget * child;
    gchar *markup;
    gint y = 0;

    gtk_table_set_col_spacings(table, 8);
    gtk_table_set_row_spacings(table, 8);

    child = gtk_label_new(NULL);
    markup = g_markup_printf_escaped("<span weight='bold'>%s:</span>",  _("Listen on ports"));
    gtk_label_set_markup(GTK_LABEL(child), markup);
    g_free(markup);
    gtk_misc_set_alignment(GTK_MISC(child), 0.0, 0.5);
    gtk_table_attach_defaults(table, child, 0, 1, y, y+1);
    //++y;

    child = gtk_label_new(_("from:"));
    gtk_misc_set_alignment(GTK_MISC(child), 1.0, 0.5);
    gtk_table_attach_defaults(table, child, 1, 2, y, y+1);
    child = gtk_spin_button_new_with_range(1025, G_MAXINT, 1);
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(child), (gdouble) ts->port_min);
    gtk_table_attach_defaults(table, child, 2, 3, y, y+1);
    g_signal_connect(child, "value-changed", G_CALLBACK(int_value_changed), &ts->port_min);

    child = gtk_label_new(_("to:"));
    gtk_misc_set_alignment(GTK_MISC(child), 1.0, 0.5);
    gtk_table_attach_defaults(table, child, 4, 5, y, y+1);
    child = gtk_spin_button_new_with_range(1025, G_MAXINT, 1);
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(child), (gdouble) ts->port_max);
    gtk_table_attach_defaults(table, child, 5, 6, y, y+1);
    g_signal_connect(child, "value-changed", G_CALLBACK(int_value_changed), &ts->port_max);
    ++y;

    child = gtk_label_new(NULL);
    markup = g_markup_printf_escaped("<span weight='bold'>%s:</span>",  _("Active torrents"));
    gtk_label_set_markup(GTK_LABEL(child), markup);
    g_free(markup);
    gtk_misc_set_alignment(GTK_MISC(child), 0.0, 0.5);
    gtk_table_attach_defaults(table, child, 0, 1, y, y+1);
    //++y;
    child = gtk_spin_button_new_with_range(0, 1024, 1);
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(child), (gdouble) ts->active_torrents);
    gtk_table_attach_defaults(table, child, 2, 3, y, y+1);
    g_signal_connect(child, "value-changed", G_CALLBACK(int_value_changed), &ts->active_torrents);
    ++y;

    child = gtk_label_new(NULL);
    markup = g_markup_printf_escaped("<span weight='bold'>%s:</span>",  _("Download to"));
    gtk_label_set_markup(GTK_LABEL(child), markup);
    g_free(markup);
    gtk_misc_set_alignment(GTK_MISC(child), 0.0, 0.5);
    gtk_table_attach_defaults(table, child, 0, 1, y, y+1);
    //++y;
    child = gtk_file_chooser_button_new(_("Torrent download folder"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (child), ts->save_dir);
    gtk_table_attach_defaults(table, child, 1, 6, y, y+1);
    ++y;

    child = gtk_label_new(NULL);
    markup = g_markup_printf_escaped("<span weight='bold'>%s:</span>",  _("Seed until"));
    gtk_label_set_markup(GTK_LABEL(child), markup);
    g_free(markup);
    gtk_misc_set_alignment(GTK_MISC(child), 0.0, 0.5);
    gtk_table_attach_defaults(table, child, 0, 1, y, y+1);
    //++y;
    child = gtk_label_new(_("upload/download ratio > "));
    gtk_misc_set_alignment(GTK_MISC(child), 1.0, 0.5);
    gtk_table_attach_defaults(table, child, 1, 5, y, y+1);
    child = gtk_spin_button_new_with_range(1, 10, 0.05);
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(child), ts->seed_ratio);
    gtk_table_attach_defaults(table, child, 5, 6, y, y+1);
    g_signal_connect(child, "value-changed", G_CALLBACK(float_value_changed), &ts->seed_ratio);
    ++y;

    child = gtk_label_new(NULL);
    markup = g_markup_printf_escaped("<span weight='bold'>%s:</span>",  _("Maximum"));
    gtk_label_set_markup(GTK_LABEL(child), markup);
    g_free(markup);
    gtk_misc_set_alignment(GTK_MISC(child), 0.0, 0.5);
    gtk_table_attach_defaults(table, child, 0, 1, y, y+1);
    //++y;

    child = gtk_label_new(_("connections:"));
    gtk_misc_set_alignment(GTK_MISC(child), 1.0, 0.5);
    gtk_table_attach_defaults(table, child, 1, 2, y, y+1);
    child = gtk_spin_button_new_with_range(2, 1024, 1);
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(child), (gdouble) ts->connections);
    gtk_table_attach_defaults(table, child, 2, 3, y, y+1);
    g_signal_connect(child, "value-changed", G_CALLBACK(int_value_changed), &ts->connections);

    child = gtk_label_new(_("uploads:"));
    gtk_misc_set_alignment(GTK_MISC(child), 1.0, 0.5);
    gtk_table_attach_defaults(table, child, 4, 5, y, y+1);
    child = gtk_spin_button_new_with_range(1, 1024, 1);
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(child), (gdouble) ts->uploads);
    gtk_table_attach_defaults(table, child, 5, 6, y, y+1);
    g_signal_connect(child, "value-changed", G_CALLBACK(int_value_changed), &ts->uploads);
    ++y;
    child = gtk_label_new(_("at least 2 connections and 1 upload per torrent"));
    gtk_misc_set_alignment(GTK_MISC(child), 0.5, 0.5);
    gtk_table_attach_defaults(table, child, 0, 6, y, y+1);
    ++y;

    child = gtk_label_new(NULL);
    markup = g_markup_printf_escaped("<span weight='bold'>%s:</span>", _("Speed limit (KB/s)"));
    gtk_label_set_markup(GTK_LABEL(child), markup);
    g_free(markup);
    gtk_misc_set_alignment(GTK_MISC(child), 0.0, 0.5);
    gtk_table_attach_defaults(table, child, 0, 1, y, y+1);
    //++y;

    child = gtk_label_new(_("download:"));
    gtk_misc_set_alignment(GTK_MISC(child), 1.0, 0.5);
    gtk_table_attach_defaults(table, child, 1, 2, y, y+1);
    child = gtk_spin_button_new_with_range(-1, 1024, 1);
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(child), (gdouble) ts->down_speed);
    gtk_table_attach_defaults(table, child, 2, 3, y, y+1);
    g_signal_connect(child, "value-changed",  G_CALLBACK(int_value_changed), &ts->down_speed);

    child = gtk_label_new(_("upload:"));
    gtk_misc_set_alignment(GTK_MISC(child), 1.0, 0.5);
    gtk_table_attach_defaults(table, child, 4, 5, y, y+1);
    child = gtk_spin_button_new_with_range(-1, 1024, 1);
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(child), (gdouble) ts->up_speed);
    gtk_table_attach_defaults(table, child, 5, 6, y, y+1);
    g_signal_connect(child, "value-changed",  G_CALLBACK(int_value_changed), &ts->up_speed);
    ++y;
    child = gtk_label_new(_("-1 = no limit"));
    gtk_misc_set_alignment(GTK_MISC(child), 0.5, 0.5);
    gtk_table_attach_defaults(table, child, 0, 6, y, y+1);
    ++y;

    child = gtk_label_new(NULL);
    markup = g_markup_printf_escaped("<span weight='bold'>%s:</span>", _("Use extensions"));
    gtk_label_set_markup(GTK_LABEL(child), markup);
    g_free(markup);
    gtk_misc_set_alignment(GTK_MISC(child), 0.0, 0.5);
    gtk_table_attach_defaults(table, child, 0, 1, y, y+1);
    //++y;

    child = gtk_label_new(_("PEX:"));
    gtk_misc_set_alignment(GTK_MISC(child), 1.0, 0.5);
    gtk_table_attach_defaults(table, child, 1, 2, y, y+1);
    child = gtk_combo_box_new_text();
    gtk_combo_box_append_text(GTK_COMBO_BOX(child), _("disabled"));
    gtk_combo_box_append_text(GTK_COMBO_BOX(child), _("enabled"));
    gtk_combo_box_set_active(GTK_COMBO_BOX(child), ts->use_pex);
    gtk_table_attach_defaults(table, child, 2, 3, y, y+1);
    g_signal_connect(child, "changed",  G_CALLBACK(enum_value_changed), &ts->use_pex);

    child = gtk_label_new(_("DHT:"));
    gtk_misc_set_alignment(GTK_MISC(child), 1.0, 0.5);
    gtk_table_attach_defaults(table, child, 4, 5, y, y+1);
    child = gtk_combo_box_new_text();
    gtk_combo_box_append_text(GTK_COMBO_BOX(child), _("never"));
    gtk_combo_box_append_text(GTK_COMBO_BOX(child), _("as fallback"));
    gtk_combo_box_append_text(GTK_COMBO_BOX(child), _("allways"));
    gtk_combo_box_set_active(GTK_COMBO_BOX(child), ts->use_dht);
    gtk_table_attach_defaults(table, child, 5, 6, y, y+1);
    g_signal_connect(child, "changed",  G_CALLBACK(enum_value_changed), &ts->use_dht);
    ++y;

    child = gtk_label_new(NULL);
    markup = g_markup_printf_escaped("<span weight='bold'>%s:</span>", _("Save settings"));
    gtk_label_set_markup(GTK_LABEL(child), markup);
    g_free(markup);
    gtk_misc_set_alignment(GTK_MISC(child), 0.0, 0.5);
    gtk_table_attach_defaults(table, child, 0, 1, y, y+1);

    child = gtk_label_new(_("every:"));
    gtk_misc_set_alignment(GTK_MISC(child), 1.0, 0.5);
    gtk_table_attach_defaults(table, child, 1, 2, y, y+1);
    child = gtk_spin_button_new_with_range(60, 7200, 15);
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(child), (gdouble) ts->save_freq);
    gtk_table_attach_defaults(table, child, 2, 3, y, y+1);
    g_signal_connect(child, "value-changed",  G_CALLBACK(int_value_changed), &ts->save_freq);
    child = gtk_label_new(_("seconds"));
    gtk_misc_set_alignment(GTK_MISC(child), 0.0, 0.5);
    gtk_table_attach_defaults(table, child, 3, 6, y, y+1);


    return GTK_WIDGET(table);
}
